#!/bin/sh
#
# Copyright (c) 2006,2008-2013 LAAS/CNRS
# Copyright (c) 2001-2002 Alistair G. Crooks.
# All rights reserved.
#
# This project includes software developed by the NetBSD Foundation, Inc.
# and its contributors. It is derived from the 'pkgsrc' project
# (http://www.pkgsrc.org).
#
# Redistribution  and  use in source   and binary forms,  with or without
# modification, are permitted provided that  the following conditions are
# met:
#
#   1. Redistributions  of  source code must  retain  the above copyright
#      notice, this list of conditions and the following disclaimer.
#   2. Redistributions in binary form must  reproduce the above copyright
#      notice,  this list of  conditions and  the following disclaimer in
#      the  documentation   and/or  other  materials   provided with  the
#      distribution.
#   3. All advertising materials mentioning   features or use of this
#      software must display the following acknowledgement:
#	This product includes software developed by Alistair G. Crooks
#	for the NetBSD project.
#   4. Neither the  name  of The NetBSD Foundation  nor the names  of its
#      contributors  may be  used to endorse or promote  products derived
#      from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
# ANY  EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES   OF MERCHANTABILITY AND  FITNESS  FOR  A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO  EVENT SHALL THE AUTHOR OR  CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT,  INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING,  BUT  NOT LIMITED TO, PROCUREMENT  OF
# SUBSTITUTE  GOODS OR SERVICES;  LOSS   OF  USE,  DATA, OR PROFITS;   OR
# BUSINESS  INTERRUPTION) HOWEVER CAUSED AND  ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE  USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# From $NetBSD: bootstrap,v 1.88 2006/11/06 21:08:42 tv Exp $
#
#                                       Anthony Mallet on Sun Oct  1 2006
#

# where the building takes place
bootstrapdir=`dirname "$0"`
bootstrapdir=`cd "${bootstrapdir}" && pwd`
pkgsrcdir=`dirname "${bootstrapdir}"`
wrkdir="`pwd`/work"

usage="Usage: $0 "'
    [ --workdir <workdir> ]
    [ --prefix <prefix> ]
    [ --pkgdbdir <pkgdbdir> ]
    [ --pkgmandir <pkgmandir> ]
    [ --sysconfdir <sysconfdir> ]
    [ --fetch-cmd <ftp command> ]
    [ --compiler <compiler> ]
    [ --make <make command> ]
    [ --help ]'

die()
{
	echo >&2 "$@"
	exit 1
}

echo_msg()
{
    echo "===> $@"
}

check_prog()
{
    _var="$1"; _name="$2"

    eval _tmp=\"\$$_var\"
    if [ "x$_tmp" != "x" ]; then
	# Variable is already set (by the user, for example)
	return 0
    fi

    for _d in `echo $PATH | tr ':' ' '`; do
	if [ -x "$_d/$_name" ]; then
	    # Program found
	    eval $_var=\""$_d/$_name"\"
	    return 1
	fi
    done

    die "$_name not found in path."
}

# run a command, abort if it fails
run_cmd()
{
    echo_msg "running: $@"
    eval "$@"
    ret=$?
    if [ $ret -ne 0 ]; then
	echo_msg "exited with status $ret"
	die "aborted."
    fi
}

# run a command verbosely
echo_cmd()
{
    echo "running: $@"
    eval "$@"
}

mkdir_p()
{
    run_cmd "mkdir -p $@"
}

copy_src()
{
    _src="$1"; _dst="$2"
    if [ ! -d $wrkdir/$_dst ]; then
	mkdir_p $wrkdir/$_dst
    fi
    $cpprog -r $_src/* $wrkdir/$_dst
}

get_optarg()
{
    expr "x$1" : "x[^=]*=\\(.*\\)"
}

# user configurable options
prefix=/opt/openrobots
pkgdbdir=
mandir=
sysconfdir=
compiler=
gmake=

while [ $# -gt 0 ]; do
	case $1 in
	--workdir=*)		wrkdir=`get_optarg "$1"` ;;
	--workdir)		wrkdir="$2"; shift ;;
	--prefix=*)		prefix=`get_optarg "$1"` ;;
	--prefix)		prefix="$2"; shift ;;
	--pkgdbdir=*)		pkgdbdir=`get_optarg "$1"` ;;
	--pkgdbdir)		pkgdbdir="$2"; shift ;;
	--mandir=*)		mandir=`get_optarg "$1"` ;;
	--mandir)		mandir="$2"; shift ;;
	--sysconfdir=*)		sysconfdir=`get_optarg "$1"` ;;
	--sysconfdir)		sysconfdir="$2"; shift ;;
	--fetch-cmd=*)		fetch_cmd=`get_optarg "$1"` ;;
	--fetch-cmd)		fetch_cmd="$a"; shift ;;
	--compiler=*)		compiler=`get_optarg "$1"` ;;
	--compiler)		compiler="$2"; shift ;;
	--make=*)		gmake=`get_optarg "$1"` ;;
	--make)			gmake="$2"; shift ;;
	--help)			echo "$usage"; exit ;;
	-h)			echo "$usage"; exit ;;
	--*)			echo "$usage"; exit 1 ;;
	esac
	shift
done

# --- set defaults ---------------------------------------------------------

# set defaults for system locations if not already set by the user
[ -z "$prefix" ] && prefix=/opt/openrobots
[ -z "$pkgdbdir" ] && pkgdbdir=${prefix}/var/db/robotpkg
[ -z "$mandir" ] && mandir=${prefix}/man
[ -z "$sysconfdir" ] && sysconfdir=${prefix}/etc

[ -z "$compiler" ] && compiler_set='# '
[ -z "$pkgdbdir" ] && pkgdbdir_set='# '
[ -z "$mandir" ] && mandir=${prefix}/man
[ -z "$sysconfdir" ] && sysconfdir_set='# '

# export OPSYS and MACHINE_ARCH for pkg_install
read OPSYS OS_RELEASE MACHINE_ARCH <<EOF
`sh $pkgsrcdir/mk/platform/opsys.sh`
EOF
export OPSYS
export MACHINE_ARCH

# set programs
if [ -z "$gmake" ]; then
    case "$OPSYS" in
        NetBSD|DragonFly|SunOS|Solaris)
	    gmake=gmake
	    ;;
        *)
            gmake=make
            ;;
    esac
fi

if [ -n "$SH" ]; then
    shprog="$SH"
else
    check_prog shprog sh
fi

if [ -n "$CP" ]; then
    cpprog="$CP"
else
    check_prog cpprog cp
fi


# --- check compatibility --------------------------------------------------

v=`$gmake --version 2>&1 ||:`
case "$v" in *"Make 3.80"*)
  echo "===================================================================="
  echo "GNU-make>=3.81 is required for robotpkg."
  echo "Please update your $gmake program. "
  echo
  echo "You can use the '--make' option to select another make program."
  echo "See $0 --help."
  echo "===================================================================="
  die '***' Fatal Error
  ;;
esac


# --- preserve existing settings -------------------------------------------

test -f ${sysconfdir}/robotpkg.conf && {
  echo "===================================================================="
  echo "An existing installation has been detected in"
  echo "${sysconfdir}/robotpkg.conf"
  echo
  echo "If you really want to bootstrap to this location, move away this file"
  echo "first. After bootstrap, you will have to manually merge your previous"
  echo "settings into the new robotpkg.conf file created during bootstrap."
  echo "===================================================================="
  die '***' Fatal Error
}

build_start=`date`
echo_msg "bootstrap command: $0 $@"
echo_msg "bootstrap started: $build_start"


# --- create the initial prefix directory ----------------------------

[ -x "$prefix" ] || {
  echo_msg "Creating ${prefix} directory"
  echo_cmd mkdir -p "$prefix" ||
    die "Please create a directory ${prefix}, writable by you.
You can also do $0 --prefix <path> to bootstrap with <path> prefix."

  echo_cmd chmod u+rwx "${prefix}" ||
    die "Could not make ${prefix} writable by you. Please do it manually."
}

[ -r "$prefix" -a -w "$prefix" ] ||
  die "Please make ${prefix} readable and writable by you."

# create installation directories
mkdir_p $prefix $pkgdbdir $prefix/sbin
mkdir_p $mandir/man1 $mandir/man5 $mandir/man7


# --- set up an example mk.conf file ---------------------------------

export MKCONF_EXAMPLE=${wrkdir}/robotpkg.conf.example

echo_msg "Creating robotpkg.conf.example in ${wrkdir}"
mkdir_p ${wrkdir}

# process robotpkg.conf template with handy shortcuts
while read line; do
  eval echo \"$line\"
done <${pkgsrcdir}/bootstrap/robotpkg.conf.example >${MKCONF_EXAMPLE}


# --- build libnbcompat ----------------------------------------------

echo_msg "Building libnbcompat"
copy_src $pkgsrcdir/pkgtools/libnbcompat/dist libnbcompat
run_cmd "(						\
    cd $wrkdir/libnbcompat;				\
    $shprog ./configure -C $configure_quiet_flags	\
	--prefix=$prefix --sysconfdir=$sysconfdir	\
	--enable-bsd-getopt --enable-db			\
    && $gmake						\
)"


# --- bootstrap pkg_install ------------------------------------------

# This will install a minimal version of the robotpkg_admin tools.
# Then the regular robotpkg framework will be functional and the regular
# robotpkg_admin tools will be pulled up as a build dependency of every
# package.
echo_msg "Installing package administrative tools"
copy_src $pkgsrcdir/pkgtools/pkg_install/dist pkg_install
run_cmd "(							\
    cd $wrkdir/pkg_install;					\
    env $BSTRAP_ENV						\
    CPPFLAGS='$CPPFLAGS -I../libnbcompat -I../../libnbcompat'	\
    LDFLAGS='$LDFLAGS -L../libnbcompat -L../../libnbcompat'	\
    LIBS='-lnbcompat'						\
    $shprog ./configure -C $configure_quiet_flags		\
	--enable-bootstrap					\
	--prefix=$prefix --sysconfdir=$sysconfdir		\
	--with-pkgdbdir=$pkgdbdir --mandir=$mandir		\
	$pkg_install_args					\
    && $gmake && $gmake install					\
)"

# Aggressively remove any previous pkg_install entries in pkgdb.
#
oldpkg=`$prefix/sbin/robotpkg_admin -b -d $pkgdbdir -S lsall pkg_install ||:`
test -z "$oldpkg" || echo_msg "Removing exisiting pkg_install entries"
for p in $oldpkg; do
    run_cmd "$prefix/sbin/robotpkg_admin delete $p"
    test -d $pkgdbdir/$p && run_cmd "rm -rf $pkgdbdir/$p"
done

# Register the installed package, with version = 0 so that the regular
# package will be fetched automatically when installing other software.
echo_msg "Registering installed package"
run_cmd "(							\
    cd $pkgsrcdir/pkgtools/pkg_install &&			\
    $gmake MAKECONF=${MKCONF_EXAMPLE} VERSION=0 PKGREVISION=0	\
	ROBOTPKG_BASE=$prefix NO_DEPENDS=yes			\
	WRKSRC=$wrkdir/pkg_install PLIST_SRC=PLIST.bootstrap	\
	bootstrap-register					\
)"

# Install sample config file
sysconffile=${sysconfdir}/robotpkg.conf
mkdir_p ${sysconfdir}
run_cmd $cpprog ${MKCONF_EXAMPLE} ${sysconffile}


# --- cleanup --------------------------------------------------------

run_cmd ${bootstrapdir}/cleanup

hline="==========================================================================="
echo ""
echo "$hline"
echo ""
echo "Hopefully everything is now complete."
echo ""
echo "An example robotpkg.conf file with the settings you provided to \"bootstrap\""
echo "has been created for you. It can be found in:"
echo ""
echo "      ${sysconffile}"
echo ""
echo "You can start building packages by changing to some package directory"
echo "and then doing \"${gmake} update\" in that directory."
#echo
#echo "You can find extensive documentation of the robotics packages collection"
#echo "in $pkgsrcdir/doc/robotpkg.txt."
echo ""
if test "$prefix" != "/opt/openrobots"; then
  echo "==> Please either add $prefix/sbin to your PATH variable"
  echo "or, alternatively, set the ROBOTPKG_BASE variable to $prefix"
  echo "in your environment. Otherwise robotpkg won't work."
  echo ""
fi
echo "Thank you."
echo ""
echo "$hline"
echo ""

echo_msg "bootstrap started: $build_start"
echo_msg "bootstrap ended:   `date`"

exit 0
